#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <errno.h> // 定义了全局错误码 errno
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/sysmacros.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>

char type(mode_t mode){
    if(S_ISREG(mode))return '-';
    if(S_ISDIR(mode))return 'd';
    if(S_ISCHR(mode))return 'c';
    if(S_ISBLK(mode))return 'b';
    if(S_ISFIFO(mode))return 'f';
    if(S_ISLNK(mode))return 'l';
    if(S_ISSOCK(mode))return 's';
}

char *permision(mode_t mode){
    static char buf[10];
    char pm[] = {'r', 'w', 'x'};
    for(int i = 0; i < 9; i++)
        buf[i] = mode & (0400>>i) ? pm[i % 3] : '-';
    return buf;
}

int main(int argc, char const *argv[])
{
    //打印当前目录路径
    char path[100];
    // getcwd(path, 100);
    // printf("当前目录路径是:%s\n", path);

    //打开目录获得目录指针
    //注：打开目录并不是进入目录，而是获得目录句柄
    DIR *dp = opendir(argv[1]);
    if(dp == NULL){
        perror("打开目录失败");
        return -1;
    }
    // //再次查看打开目录后当前目录路径,结果：并未改变
    // getcwd(path, 100);
    // printf("当前目录路径是:%s\n", path);
    
    //进入目录
    chdir(argv[1]);
    getcwd(path, 100);
    printf("当前目录路径是:%s\n", path);

    //循环读取目录项
    struct dirent *ep = NULL;
    struct stat st;

    while(1){
        ep = readdir(dp);

        if(ep == NULL)break;

        if(ep->d_name[0] == '.')continue;

        bzero(&st, sizeof(st));
        if(stat(ep->d_name, &st) == -1)
            perror("stat失败");
        
        //文件类型
        printf("%c", type(st.st_mode));

        //文件权限
        printf("%s ", permision(st.st_mode));

        //文件别名数量
        printf("%ld ", st.st_nlink);

        //文件所有组、所属组
        printf("%s %s ", getpwuid(st.st_uid)->pw_name, getgrgid(st.st_gid)->gr_name);
        
        // 文件的大小
        if(S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
            printf("%u %u ", major(st.st_rdev), minor(st.st_mode));
        else printf("%ld ", st.st_size);

        //文件最近访问时间
        char file_atime[20];
        strncpy(file_atime, ctime(&st.st_atime), 20);
        printf("%s ", file_atime);
        
        // 文件的名字
        printf("%s\n", ep->d_name);
    }
    return 0;
}
